/* eslint-disable */
const noop = () => {
};

module.exports = function (redisClient, module) {
    const helpers = module.helpers.redis;

    module.setObject = function (key, data, callback) {
        callback = callback || noop;
        if (!key || !data) {
            return callback();
        }
        delete data[''];

        Object.keys(data).forEach((key) => {
            if (data[key] === undefined) {
                delete data[key];
            }
        });

        redisClient.hmset(key, data, callback);
    };

    module.setObjectField = function (key, field, value, callback) {
        callback = callback || noop();
        redisClient.hset(key, field, value, callback);
    };

    module.getObject = function (key, callback) {
        redisClient.hgetall(key, callback);
    };

    module.getObjects = function (keys, callback) {
        helpers.multiKeys(redisClient, 'hgetall', keys, callback);
    };

    module.getObjectField = function (key, field, callback) {
        module.getObjectFields(key, [field], (err, data) => {
            callback(err, data ? data[field] : null);
        });
    };

    module.getObjectFields = function (key, fields, callback) {
        module.getObjectsFields([key], fields, (err, results) => {
            callback(err, results ? results[0] : null);
        });
    };

    module.getObjectsFields = function (keys, fields, callback) {
        if (!Array.isArray(fields) || !fields.length) {
            return callback(null, keys.map(() => ({})));
        }
        const multi = redisClient.multi();

        for (let x = 0; x < keys.length; x += 1) {
            multi.hmget(...[keys[x], ...fields]);
        }

        function makeObject(array) {
            const obj = {};

            for (let i = 0, ii = fields.length; i < ii; i += 1) {
                obj[fields[i]] = array[i];
            }
            return obj;
        }

        multi.exec((err, results) => {
            if (err) {
                return callback(err);
            }

            results = results.map(makeObject);
            callback(null, results);
        });
    };

    module.getObjectKeys = function (key, callback) {
        redisClient.hkeys(key, callback);
    };

    module.getObjectValues = function (key, callback) {
        redisClient.hvals(key, callback);
    };

    module.isObjectField = function (key, field, callback) {
        redisClient.hexists(key, field, (err, exists) => {
            callback(err, exists === 1);
        });
    };

    module.isObjectFields = function (key, fields, callback) {
        helpers.multiKeyValues(redisClient, 'hexists', key, fields, (err, results) => {
            callback(err, Array.isArray(results) ? helpers.resultsToBool(results) : null);
        });
    };

    module.deleteObjectField = function (key, field, callback) {
        callback = callback || noop();
        if (field === null) {
            return setImmediate(callback);
        }
        redisClient.hdel(key, field, callback);
    };

    module.deleteObjectFields = function (key, fields, callback) {
        helpers.multiKeyValues(redisClient, 'hdel', key, fields, callback);
    };

    module.incrObjectField = function (key, field, callback) {
        redisClient.hincrby(key, field, 1, callback);
    };

    module.decrObjectField = function (key, field, callback) {
        redisClient.hincrby(key, field, -1, callback);
    };

    module.incrObjectFieldBy = function (key, field, value, callback) {
        redisClient.hincrby(key, field, value, callback);
    };
};
/* eslint-enable */
